{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "bLEEW13uCtiJ"
   },
   "source": [
    "<a href=\"https://colab.research.google.com/github/jeffheaton/t81_558_deep_learning/blob/master/t81_558_class_03_2_keras.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "5oX6K_-JCtiL"
   },
   "source": [
    "# T81-558: Applications of Deep Neural Networks\n",
    "**Module 3: Introduction to TensorFlow**\n",
    "* Instructor: [Jeff Heaton](https://sites.wustl.edu/jeffheaton/), McKelvey School of Engineering, [Washington University in St. Louis](https://engineering.wustl.edu/Programs/Pages/default.aspx)\n",
    "* For more information visit the [class website](https://sites.wustl.edu/jeffheaton/t81-558/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "FzlMdsudCtiL"
   },
   "source": [
    "# Module 3 Material\n",
    "\n",
    "* Part 3.1: Deep Learning and Neural Network Introduction [[Video]](https://www.youtube.com/watch?v=zYnI4iWRmpc&list=PLjy4p-07OYzulelvJ5KVaT2pDlxivl_BN) [[Notebook]](https://github.com/jeffheaton/t81_558_deep_learning/blob/master/t81_558_class_03_1_neural_net.ipynb)\n",
    "* **Part 3.2: Introduction to Tensorflow and Keras** [[Video]](https://www.youtube.com/watch?v=PsE73jk55cE&list=PLjy4p-07OYzulelvJ5KVaT2pDlxivl_BN) [[Notebook]](https://github.com/jeffheaton/t81_558_deep_learning/blob/master/t81_558_class_03_2_keras.ipynb)\n",
    "* Part 3.3: Saving and Loading a Keras Neural Network [[Video]](https://www.youtube.com/watch?v=-9QfbGM1qGw&list=PLjy4p-07OYzulelvJ5KVaT2pDlxivl_BN) [[Notebook]](https://github.com/jeffheaton/t81_558_deep_learning/blob/master/t81_558_class_03_3_save_load.ipynb)\n",
    "* Part 3.4: Early Stopping in Keras to Prevent Overfitting [[Video]](https://www.youtube.com/watch?v=m1LNunuI2fk&list=PLjy4p-07OYzulelvJ5KVaT2pDlxivl_BN) [[Notebook]](https://github.com/jeffheaton/t81_558_deep_learning/blob/master/t81_558_class_03_4_early_stop.ipynb)\n",
    "* Part 3.5: Extracting Weights and Manual Calculation [[Video]](https://www.youtube.com/watch?v=7PWgx16kH8s&list=PLjy4p-07OYzulelvJ5KVaT2pDlxivl_BN) [[Notebook]](https://github.com/jeffheaton/t81_558_deep_learning/blob/master/t81_558_class_03_5_weights.ipynb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "CpVJpj2DCtiM"
   },
   "source": [
    "# Google CoLab Instructions\n",
    "\n",
    "The following code ensures that Google CoLab is running the correct version of TensorFlow."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "wU1AMzx8CtiM",
    "outputId": "24a17c67-4563-471f-9955-dfadd0f171d7"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Note: using Google CoLab\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    %tensorflow_version 2.x\n",
    "    COLAB = True\n",
    "    print(\"Note: using Google CoLab\")\n",
    "except:\n",
    "    print(\"Note: not using Google CoLab\")\n",
    "    COLAB = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "1Zg-zNx0CtiN"
   },
   "source": [
    "# Part 3.2: Introduction to Tensorflow and Keras\n",
    "\n",
    "TensorFlow [[Cite:GoogleTensorFlow]](https://research.google/pubs/pub45381/) is an open-source software library for machine learning in various kinds of perceptual and language understanding tasks. It is currently used for research and production by different teams in many commercial Google products, such as speech recognition, Gmail, Google Photos, and search, many of which had previously used its predecessor DistBelief. TensorFlow was originally developed by the Google Brain team for Google's research and production purposes and later released under the Apache 2.0 open source license on November 9, 2015.\n",
    "\n",
    "* [TensorFlow Homepage](https://www.tensorflow.org/)\n",
    "* [TensorFlow GitHib](https://github.com/tensorflow/tensorflow)\n",
    "* [TensorFlow Google Groups Support](https://groups.google.com/forum/#!forum/tensorflow)\n",
    "* [TensorFlow Google Groups Developer Discussion](https://groups.google.com/a/tensorflow.org/forum/#!forum/discuss)\n",
    "* [TensorFlow FAQ](https://www.tensorflow.org/resources/faq)\n",
    "\n",
    "## Why TensorFlow\n",
    "\n",
    "* Supported by Google\n",
    "* Works well on Windows, Linux, and Mac\n",
    "* Excellent GPU support\n",
    "* Python is an easy to learn programming language\n",
    "* Python is extremely popular in the data science community\n",
    "\n",
    "## Deep Learning Tools\n",
    "TensorFlow is not the only game in town. The biggest competitor to TensorFlow/Keras is PyTorch. Listed below are some of the deep learning toolkits actively being supported:\n",
    "\n",
    "* **[TensorFlow](https://www.tensorflow.org/)** - Google's deep learning API.  The focus of this class, along with Keras.\n",
    "* **[Keras](https://keras.io/)** - Acts as a higher-level to Tensorflow.\n",
    "* **[PyTorch](https://pytorch.org/)** - PyTorch is an open-source machine learning library based on the Torch library, used for computer vision and natural language applications processing. Facebook's AI Research lab primarily develops PyTorch. \n",
    "\n",
    "Other deep learning tools:\n",
    "\n",
    "* **[Deeplearning4J](http://deeplearning4j.org/)** - Java-based. Supports all major platforms. GPU support in Java!\n",
    "* **[H2O](http://www.h2o.ai/)** - Java-based.  \n",
    "\n",
    "In my opinion, the two primary Python libraries for deep learning are PyTorch and Keras. Generally, PyTorch requires more lines of code to perform the deep learning applications presented in this course. This trait of PyTorch gives Keras an easier learning curve than PyTorch. However, if you are creating entirely new neural network structures in a research setting, PyTorch can make for easier access to some of the low-level internals of deep learning.\n",
    "\n",
    "## Using TensorFlow Directly\n",
    "\n",
    "Most of the time in the course, we will communicate with TensorFlow using Keras [[Cite:franccois2017deep]](https://www.manning.com/books/deep-learning-with-python), which allows you to specify the number of hidden layers and create the neural network. TensorFlow is a low-level mathematics API, similar to [Numpy](http://www.numpy.org/). However, unlike Numpy, TensorFlow is built for deep learning. TensorFlow compiles these compute graphs into highly efficient C++/[CUDA](https://en.wikipedia.org/wiki/CUDA) code.\n",
    "\n",
    "## TensorFlow Linear Algebra Examples\n",
    "\n",
    "TensorFlow is a library for linear algebra. Keras is a higher-level abstraction for neural networks that you build upon TensorFlow. In this section, I will demonstrate some basic linear algebra that directly employs TensorFlow and does not use Keras. First, we will see how to multiply a row and column matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "bkh9pHqPCtiO",
    "outputId": "bb56c591-c48e-4b04-ea8e-047fcf770bb7"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([[12.]], shape=(1, 1), dtype=float32)\n",
      "12.0\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "# Create a Constant op that produces a 1x2 matrix.  The op is\n",
    "# added as a node to the default graph.\n",
    "#\n",
    "# The value returned by the constructor represents the output\n",
    "# of the Constant op.\n",
    "matrix1 = tf.constant([[3., 3.]])\n",
    "\n",
    "# Create another Constant that produces a 2x1 matrix.\n",
    "matrix2 = tf.constant([[2.],[2.]])\n",
    "\n",
    "# Create a Matmul op that takes 'matrix1' and 'matrix2' as inputs.\n",
    "# The returned value, 'product', represents the result of the matrix\n",
    "# multiplication.\n",
    "product = tf.matmul(matrix1, matrix2)\n",
    "\n",
    "print(product)\n",
    "print(float(product))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pMrXqwskCtiP"
   },
   "source": [
    "This example multiplied two TensorFlow constant tensors.  Next, we will see how to subtract a constant from a variable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "qKyFCaoTCtiP",
    "outputId": "d215868a-b0d5-40ca-c65e-5fca8ab36c9a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([-2. -1.], shape=(2,), dtype=float32)\n",
      "[-2. -1.]\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "x = tf.Variable([1.0, 2.0])\n",
    "a = tf.constant([3.0, 3.0])\n",
    "\n",
    "# Add an op to subtract 'a' from 'x'.  Run it and print the result\n",
    "sub = tf.subtract(x, a)\n",
    "print(sub)\n",
    "print(sub.numpy())\n",
    "# ==> [-2. -1.]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "epQ9LrM6CtiP"
   },
   "source": [
    "Of course, variables are only useful if their values can be changed.  The program can accomplish this change in value by calling the assign function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "vtnW5aU-CtiP",
    "outputId": "3c09cd43-af12-4d83-c6e5-4085e745aa8e"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<tf.Variable 'UnreadVariable' shape=(2,) dtype=float32, numpy=array([4., 6.], dtype=float32)>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x.assign([4.0, 6.0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "zHwJP8MjCtiQ"
   },
   "source": [
    "The program can now perform the subtraction with this new value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "0e26Fe-GCtiQ",
    "outputId": "1e9af0e7-4542-469a-b4b9-f5a62de1d199"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([1. 3.], shape=(2,), dtype=float32)\n",
      "[1. 3.]\n"
     ]
    }
   ],
   "source": [
    "sub = tf.subtract(x, a)\n",
    "print(sub)\n",
    "print(sub.numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Rq61YFBYCtiQ"
   },
   "source": [
    "In the next section, we will see a TensorFlow example that has nothing to do with neural networks."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "iMVIS9pBCtiQ"
   },
   "source": [
    "## TensorFlow Mandelbrot Set Example\n",
    "\n",
    "Next, we examine another example where we use TensorFlow directly. To demonstrate that TensorFlow is mathematical and does not only provide neural networks, we will also first use it for a non-machine learning rendering task. The code presented here can render a [Mandelbrot set](https://en.wikipedia.org/wiki/Mandelbrot_set)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "v4ll1OLwCtiQ"
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "\n",
    "import PIL.Image\n",
    "from io import BytesIO\n",
    "from IPython.display import Image, display\n",
    "\n",
    "def render(a):\n",
    "  a_cyclic = (a*0.3).reshape(list(a.shape)+[1])\n",
    "  img = np.concatenate([10+20*np.cos(a_cyclic),\n",
    "                        30+50*np.sin(a_cyclic),\n",
    "                        155-80*np.cos(a_cyclic)], 2)\n",
    "  img[a==a.max()] = 0\n",
    "  a = img\n",
    "  a = np.uint8(np.clip(a, 0, 255))\n",
    "  f = BytesIO()\n",
    "  return PIL.Image.fromarray(a)\n",
    "\n",
    "#@tf.function\n",
    "def mandelbrot_helper(grid_c, current_values, counts,cycles):\n",
    "  \n",
    "  for i in range(cycles):\n",
    "    temp = current_values*current_values + grid_c\n",
    "    not_diverged = tf.abs(temp) < 4\n",
    "    current_values.assign(temp),\n",
    "    counts.assign_add(tf.cast(not_diverged, tf.float32))\n",
    "\n",
    "def mandelbrot(render_size,center,zoom,cycles):\n",
    "  f = zoom/render_size[0]\n",
    "  real_start = center[0]-(render_size[0]/2)*f\n",
    "  real_end = real_start + render_size[0]*f \n",
    "  imag_start = center[1]-(render_size[1]/2)*f\n",
    "  imag_end = imag_start + render_size[1]*f \n",
    "\n",
    "  real_range = tf.range(real_start,real_end,f,dtype=tf.float64)\n",
    "  imag_range = tf.range(imag_start,imag_end,f,dtype=tf.float64)\n",
    "  real, imag = tf.meshgrid(real_range,imag_range)\n",
    "  grid_c = tf.constant(tf.complex(real, imag))\n",
    "  current_values = tf.Variable(grid_c)\n",
    "  counts = tf.Variable(tf.zeros_like(grid_c, tf.float32))\n",
    "\n",
    "  mandelbrot_helper(grid_c, current_values,counts,cycles)\n",
    "  return counts.numpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "iUIw04vRCmc1"
   },
   "source": [
    "With the above code defined, we can now calculate and render a Mandlebrot plot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 515
    },
    "id": "9MZLfaYpCaO2",
    "outputId": "8b045029-3c57-46c8-8e79-cb63c2d52949"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(640, 480)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=640x480 at 0x7F7A7BD809D0>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "counts = mandelbrot(\n",
    "    #render_size=(3840,2160), # 4K\n",
    "    #render_size=(1920,1080), # HD\n",
    "    render_size=(640,480),\n",
    "    center=(-0.5,0),\n",
    "    zoom=4,\n",
    "    cycles=200\n",
    ")  \n",
    "img = render(counts)\n",
    "print(img.size)\n",
    "img\n",
    "\n",
    "#img.save(\"test.png\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ZeWypKgGCtiR"
   },
   "source": [
    "Mandlebrot rendering programs are both simple and infinitely complex at the same time. This view shows the entire Mandlebrot universe simultaneously, as a view completely zoomed out. However, if you zoom in on any non-black portion of the plot, you will find infinite hidden complexity. \n",
    "\n",
    "## Introduction to Keras\n",
    "\n",
    "[Keras](https://keras.io/) is a layer on top of Tensorflow that makes it much easier to create neural networks. Rather than define the graphs, as you see above, you set the individual layers of the network with a much more high-level API. Unless you are researching entirely new structures of deep neural networks, it is unlikely that you need to program TensorFlow directly.  \n",
    "\n",
    "**For this class, we will usually use TensorFlow through Keras, rather than direct TensorFlow**\n",
    "\n",
    "## Simple TensorFlow Regression: MPG\n",
    "\n",
    "This example shows how to encode the MPG dataset for regression and predict values. We will see if we can predict the miles per gallon (MPG) for a car based on the car's weight, cylinders, engine size, and other features.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "bmb3cFrUCtiR",
    "outputId": "7afe0626-d793-42c2-e8e2-a9c64a4e580f"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "13/13 - 1s - loss: 4316.6265 - 1s/epoch - 108ms/step\n",
      "Epoch 2/100\n",
      "13/13 - 0s - loss: 1053.9304 - 42ms/epoch - 3ms/step\n",
      "Epoch 3/100\n",
      "13/13 - 0s - loss: 400.8871 - 40ms/epoch - 3ms/step\n",
      "Epoch 4/100\n",
      "13/13 - 0s - loss: 158.8711 - 70ms/epoch - 5ms/step\n",
      "Epoch 5/100\n",
      "13/13 - 0s - loss: 122.4334 - 52ms/epoch - 4ms/step\n",
      "Epoch 6/100\n",
      "13/13 - 0s - loss: 112.2178 - 83ms/epoch - 6ms/step\n",
      "Epoch 7/100\n",
      "13/13 - 0s - loss: 109.5928 - 52ms/epoch - 4ms/step\n",
      "Epoch 8/100\n",
      "13/13 - 0s - loss: 107.0727 - 40ms/epoch - 3ms/step\n",
      "Epoch 9/100\n",
      "13/13 - 0s - loss: 105.3503 - 58ms/epoch - 4ms/step\n",
      "Epoch 10/100\n",
      "13/13 - 0s - loss: 103.4682 - 54ms/epoch - 4ms/step\n",
      "Epoch 11/100\n",
      "13/13 - 0s - loss: 102.2661 - 50ms/epoch - 4ms/step\n",
      "Epoch 12/100\n",
      "13/13 - 0s - loss: 100.2303 - 54ms/epoch - 4ms/step\n",
      "Epoch 13/100\n",
      "13/13 - 0s - loss: 99.7207 - 64ms/epoch - 5ms/step\n",
      "Epoch 14/100\n",
      "13/13 - 0s - loss: 96.4024 - 88ms/epoch - 7ms/step\n",
      "Epoch 15/100\n",
      "13/13 - 0s - loss: 93.2158 - 71ms/epoch - 5ms/step\n",
      "Epoch 16/100\n",
      "13/13 - 0s - loss: 89.9550 - 62ms/epoch - 5ms/step\n",
      "Epoch 17/100\n",
      "13/13 - 0s - loss: 88.2846 - 86ms/epoch - 7ms/step\n",
      "Epoch 18/100\n",
      "13/13 - 0s - loss: 86.3914 - 67ms/epoch - 5ms/step\n",
      "Epoch 19/100\n",
      "13/13 - 0s - loss: 84.1276 - 50ms/epoch - 4ms/step\n",
      "Epoch 20/100\n",
      "13/13 - 0s - loss: 84.8196 - 45ms/epoch - 3ms/step\n",
      "Epoch 21/100\n",
      "13/13 - 0s - loss: 84.3392 - 46ms/epoch - 4ms/step\n",
      "Epoch 22/100\n",
      "13/13 - 0s - loss: 79.5398 - 45ms/epoch - 3ms/step\n",
      "Epoch 23/100\n",
      "13/13 - 0s - loss: 77.0899 - 36ms/epoch - 3ms/step\n",
      "Epoch 24/100\n",
      "13/13 - 0s - loss: 75.8441 - 45ms/epoch - 3ms/step\n",
      "Epoch 25/100\n",
      "13/13 - 0s - loss: 75.8792 - 47ms/epoch - 4ms/step\n",
      "Epoch 26/100\n",
      "13/13 - 0s - loss: 73.5816 - 41ms/epoch - 3ms/step\n",
      "Epoch 27/100\n",
      "13/13 - 0s - loss: 74.1624 - 42ms/epoch - 3ms/step\n",
      "Epoch 28/100\n",
      "13/13 - 0s - loss: 73.7725 - 92ms/epoch - 7ms/step\n",
      "Epoch 29/100\n",
      "13/13 - 0s - loss: 69.7022 - 79ms/epoch - 6ms/step\n",
      "Epoch 30/100\n",
      "13/13 - 0s - loss: 70.4042 - 45ms/epoch - 3ms/step\n",
      "Epoch 31/100\n",
      "13/13 - 0s - loss: 66.2524 - 50ms/epoch - 4ms/step\n",
      "Epoch 32/100\n",
      "13/13 - 0s - loss: 65.7853 - 36ms/epoch - 3ms/step\n",
      "Epoch 33/100\n",
      "13/13 - 0s - loss: 63.3211 - 39ms/epoch - 3ms/step\n",
      "Epoch 34/100\n",
      "13/13 - 0s - loss: 63.5420 - 54ms/epoch - 4ms/step\n",
      "Epoch 35/100\n",
      "13/13 - 0s - loss: 62.8602 - 42ms/epoch - 3ms/step\n",
      "Epoch 36/100\n",
      "13/13 - 0s - loss: 60.7109 - 72ms/epoch - 6ms/step\n",
      "Epoch 37/100\n",
      "13/13 - 0s - loss: 59.4063 - 111ms/epoch - 9ms/step\n",
      "Epoch 38/100\n",
      "13/13 - 0s - loss: 59.1309 - 50ms/epoch - 4ms/step\n",
      "Epoch 39/100\n",
      "13/13 - 0s - loss: 59.9115 - 40ms/epoch - 3ms/step\n",
      "Epoch 40/100\n",
      "13/13 - 0s - loss: 57.2979 - 40ms/epoch - 3ms/step\n",
      "Epoch 41/100\n",
      "13/13 - 0s - loss: 55.4729 - 39ms/epoch - 3ms/step\n",
      "Epoch 42/100\n",
      "13/13 - 0s - loss: 54.6452 - 55ms/epoch - 4ms/step\n",
      "Epoch 43/100\n",
      "13/13 - 0s - loss: 55.8971 - 60ms/epoch - 5ms/step\n",
      "Epoch 44/100\n",
      "13/13 - 0s - loss: 53.4345 - 54ms/epoch - 4ms/step\n",
      "Epoch 45/100\n",
      "13/13 - 0s - loss: 52.4441 - 71ms/epoch - 5ms/step\n",
      "Epoch 46/100\n",
      "13/13 - 0s - loss: 55.9549 - 47ms/epoch - 4ms/step\n",
      "Epoch 47/100\n",
      "13/13 - 0s - loss: 56.5379 - 42ms/epoch - 3ms/step\n",
      "Epoch 48/100\n",
      "13/13 - 0s - loss: 51.9417 - 69ms/epoch - 5ms/step\n",
      "Epoch 49/100\n",
      "13/13 - 0s - loss: 50.0791 - 44ms/epoch - 3ms/step\n",
      "Epoch 50/100\n",
      "13/13 - 0s - loss: 47.1980 - 40ms/epoch - 3ms/step\n",
      "Epoch 51/100\n",
      "13/13 - 0s - loss: 48.7865 - 49ms/epoch - 4ms/step\n",
      "Epoch 52/100\n",
      "13/13 - 0s - loss: 47.3768 - 47ms/epoch - 4ms/step\n",
      "Epoch 53/100\n",
      "13/13 - 0s - loss: 46.3470 - 68ms/epoch - 5ms/step\n",
      "Epoch 54/100\n",
      "13/13 - 0s - loss: 45.0476 - 39ms/epoch - 3ms/step\n",
      "Epoch 55/100\n",
      "13/13 - 0s - loss: 43.7386 - 51ms/epoch - 4ms/step\n",
      "Epoch 56/100\n",
      "13/13 - 0s - loss: 44.1500 - 36ms/epoch - 3ms/step\n",
      "Epoch 57/100\n",
      "13/13 - 0s - loss: 42.9593 - 34ms/epoch - 3ms/step\n",
      "Epoch 58/100\n",
      "13/13 - 0s - loss: 42.6250 - 61ms/epoch - 5ms/step\n",
      "Epoch 59/100\n",
      "13/13 - 0s - loss: 42.3621 - 49ms/epoch - 4ms/step\n",
      "Epoch 60/100\n",
      "13/13 - 0s - loss: 40.9266 - 37ms/epoch - 3ms/step\n",
      "Epoch 61/100\n",
      "13/13 - 0s - loss: 40.4965 - 44ms/epoch - 3ms/step\n",
      "Epoch 62/100\n",
      "13/13 - 0s - loss: 42.0424 - 48ms/epoch - 4ms/step\n",
      "Epoch 63/100\n",
      "13/13 - 0s - loss: 42.4499 - 56ms/epoch - 4ms/step\n",
      "Epoch 64/100\n",
      "13/13 - 0s - loss: 46.3163 - 40ms/epoch - 3ms/step\n",
      "Epoch 65/100\n",
      "13/13 - 0s - loss: 40.8322 - 37ms/epoch - 3ms/step\n",
      "Epoch 66/100\n",
      "13/13 - 0s - loss: 37.7943 - 36ms/epoch - 3ms/step\n",
      "Epoch 67/100\n",
      "13/13 - 0s - loss: 37.8814 - 44ms/epoch - 3ms/step\n",
      "Epoch 68/100\n",
      "13/13 - 0s - loss: 35.4310 - 37ms/epoch - 3ms/step\n",
      "Epoch 69/100\n",
      "13/13 - 0s - loss: 36.7675 - 37ms/epoch - 3ms/step\n",
      "Epoch 70/100\n",
      "13/13 - 0s - loss: 35.9195 - 39ms/epoch - 3ms/step\n",
      "Epoch 71/100\n",
      "13/13 - 0s - loss: 33.5149 - 41ms/epoch - 3ms/step\n",
      "Epoch 72/100\n",
      "13/13 - 0s - loss: 32.8361 - 39ms/epoch - 3ms/step\n",
      "Epoch 73/100\n",
      "13/13 - 0s - loss: 32.3207 - 36ms/epoch - 3ms/step\n",
      "Epoch 74/100\n",
      "13/13 - 0s - loss: 31.6296 - 37ms/epoch - 3ms/step\n",
      "Epoch 75/100\n",
      "13/13 - 0s - loss: 32.2759 - 44ms/epoch - 3ms/step\n",
      "Epoch 76/100\n",
      "13/13 - 0s - loss: 30.4593 - 38ms/epoch - 3ms/step\n",
      "Epoch 77/100\n",
      "13/13 - 0s - loss: 32.0352 - 43ms/epoch - 3ms/step\n",
      "Epoch 78/100\n",
      "13/13 - 0s - loss: 31.4580 - 52ms/epoch - 4ms/step\n",
      "Epoch 79/100\n",
      "13/13 - 0s - loss: 29.0144 - 48ms/epoch - 4ms/step\n",
      "Epoch 80/100\n",
      "13/13 - 0s - loss: 28.9435 - 47ms/epoch - 4ms/step\n",
      "Epoch 81/100\n",
      "13/13 - 0s - loss: 29.9654 - 65ms/epoch - 5ms/step\n",
      "Epoch 82/100\n",
      "13/13 - 0s - loss: 28.3907 - 47ms/epoch - 4ms/step\n",
      "Epoch 83/100\n",
      "13/13 - 0s - loss: 27.7009 - 43ms/epoch - 3ms/step\n",
      "Epoch 84/100\n",
      "13/13 - 0s - loss: 30.1552 - 57ms/epoch - 4ms/step\n",
      "Epoch 85/100\n",
      "13/13 - 0s - loss: 27.8310 - 65ms/epoch - 5ms/step\n",
      "Epoch 86/100\n",
      "13/13 - 0s - loss: 26.1057 - 46ms/epoch - 4ms/step\n",
      "Epoch 87/100\n",
      "13/13 - 0s - loss: 25.7254 - 37ms/epoch - 3ms/step\n",
      "Epoch 88/100\n",
      "13/13 - 0s - loss: 26.4181 - 43ms/epoch - 3ms/step\n",
      "Epoch 89/100\n",
      "13/13 - 0s - loss: 26.9024 - 46ms/epoch - 4ms/step\n",
      "Epoch 90/100\n",
      "13/13 - 0s - loss: 24.3307 - 62ms/epoch - 5ms/step\n",
      "Epoch 91/100\n",
      "13/13 - 0s - loss: 24.5644 - 48ms/epoch - 4ms/step\n",
      "Epoch 92/100\n",
      "13/13 - 0s - loss: 24.2650 - 54ms/epoch - 4ms/step\n",
      "Epoch 93/100\n",
      "13/13 - 0s - loss: 24.7381 - 58ms/epoch - 4ms/step\n",
      "Epoch 94/100\n",
      "13/13 - 0s - loss: 23.8608 - 46ms/epoch - 4ms/step\n",
      "Epoch 95/100\n",
      "13/13 - 0s - loss: 22.8117 - 55ms/epoch - 4ms/step\n",
      "Epoch 96/100\n",
      "13/13 - 0s - loss: 22.2542 - 55ms/epoch - 4ms/step\n",
      "Epoch 97/100\n",
      "13/13 - 0s - loss: 21.4920 - 56ms/epoch - 4ms/step\n",
      "Epoch 98/100\n",
      "13/13 - 0s - loss: 21.7629 - 40ms/epoch - 3ms/step\n",
      "Epoch 99/100\n",
      "13/13 - 0s - loss: 21.0175 - 42ms/epoch - 3ms/step\n",
      "Epoch 100/100\n",
      "13/13 - 0s - loss: 20.8079 - 32ms/epoch - 2ms/step\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7f7a748518d0>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense, Activation\n",
    "import pandas as pd\n",
    "import io\n",
    "import os\n",
    "import requests\n",
    "import numpy as np\n",
    "from sklearn import metrics\n",
    "\n",
    "df = pd.read_csv(\n",
    "    \"https://data.heatonresearch.com/data/t81-558/auto-mpg.csv\", \n",
    "    na_values=['NA', '?'])\n",
    "\n",
    "cars = df['name']\n",
    "\n",
    "# Handle missing value\n",
    "df['horsepower'] = df['horsepower'].fillna(df['horsepower'].median())\n",
    "\n",
    "# Pandas to Numpy\n",
    "x = df[['cylinders', 'displacement', 'horsepower', 'weight',\n",
    "       'acceleration', 'year', 'origin']].values\n",
    "y = df['mpg'].values # regression\n",
    "\n",
    "# Build the neural network\n",
    "model = Sequential()\n",
    "model.add(Dense(25, input_dim=x.shape[1], activation='relu')) # Hidden 1\n",
    "model.add(Dense(10, activation='relu')) # Hidden 2\n",
    "model.add(Dense(1)) # Output\n",
    "model.compile(loss='mean_squared_error', optimizer='adam')\n",
    "model.fit(x,y,verbose=2,epochs=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "82O2rvqiCtiR"
   },
   "source": [
    "## Introduction to Neural Network Hyperparameters\n",
    "\n",
    "If you look at the above code, you will see that the neural network contains four layers. The first layer is the input layer because it contains the **input_dim** parameter that the programmer sets to be the number of inputs the dataset has. The network needs one input neuron for every column in the data set (including dummy variables).  \n",
    "\n",
    "There are also several hidden layers, with 25 and 10 neurons each. You might be wondering how the programmer chose these numbers. Selecting a hidden neuron structure is one of the most common questions about neural networks. Unfortunately, there is no right answer. These are hyperparameters. They are settings that can affect neural network performance, yet there are no clearly defined means of setting them.\n",
    "\n",
    "In general, more hidden neurons mean more capability to fit complex problems. However, too many neurons can lead to overfitting and lengthy training times. Too few can lead to underfitting the problem and will sacrifice accuracy. Also, how many layers you have is another hyperparameter. In general, more layers allow the neural network to perform more of its feature engineering and data preprocessing. But this also comes at the expense of training times and the risk of overfitting. In general, you will see that neuron counts start larger near the input layer and tend to shrink towards the output layer in a triangular fashion. \n",
    "\n",
    "Some techniques use machine learning to optimize these values. These will be discussed in [Module 8.3](t81_558_class_08_3_keras_hyperparameters.ipynb).\n",
    "\n",
    "## Controlling the Amount of Output\n",
    "\n",
    "The program produces one line of output for each training epoch. You can eliminate this output by setting the verbose setting of the fit command:\n",
    "\n",
    "* **verbose=0** - No progress output (use with Jupyter if you do not want output).\n",
    "* **verbose=1** - Display progress bar, does not work well with Jupyter.\n",
    "* **verbose=2** - Summary progress output (use with Jupyter if you want to know the loss at each epoch).\n",
    "\n",
    "## Regression Prediction\n",
    "\n",
    "Next, we will perform actual predictions. The program assigns these predictions to the **pred** variable. These are all MPG predictions from the neural network. Notice that this is a 2D array? You can always see the dimensions of what Keras returns by printing out **pred.shape**. Neural networks can return multiple values, so the result is always an array. Here the neural network only returns one value per prediction (there are 398 cars, so 398 predictions). However, a 2D range is needed because the neural network has the potential of returning more than one value.   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "HbErLyX_CtiR",
    "outputId": "9173c10d-d0e9-43c0-9bb7-cb14d082e97a"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape: (398, 1)\n",
      "[[13.070258 ]\n",
      " [10.618503 ]\n",
      " [12.105414 ]\n",
      " [13.132547 ]\n",
      " [13.046249 ]\n",
      " [ 6.5326967]\n",
      " [ 4.8309555]\n",
      " [ 5.553785 ]\n",
      " [ 5.0463076]\n",
      " [ 7.9017887]]\n"
     ]
    }
   ],
   "source": [
    "pred = model.predict(x)\n",
    "print(f\"Shape: {pred.shape}\")\n",
    "print(pred[0:10])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "jk_lWnScCtiR"
   },
   "source": [
    "We would like to see how good these predictions are.  We know the correct MPG for each car so we can measure how close the neural network was."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "vrY0Vs9oCtiR",
    "outputId": "f1c6ef77-b636-4ac0-df4d-0439977eb6eb"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final score (RMSE): 4.615160313747705\n"
     ]
    }
   ],
   "source": [
    "# Measure RMSE error.  RMSE is common for regression.\n",
    "score = np.sqrt(metrics.mean_squared_error(pred,y))\n",
    "print(f\"Final score (RMSE): {score}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "i3yqZwhnCtiS"
   },
   "source": [
    "The number printed above is the average number of predictions above or below the expected output. We can also print out the first ten cars with predictions and actual MPG."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Tl7hv8NnCtiS",
    "outputId": "a4dd79ee-8af5-4727-b595-f938814266d9"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. Car name: chevrolet chevelle malibu, MPG: 18.0, predicted MPG: [13.070258]\n",
      "2. Car name: buick skylark 320, MPG: 15.0, predicted MPG: [10.618503]\n",
      "3. Car name: plymouth satellite, MPG: 18.0, predicted MPG: [12.105414]\n",
      "4. Car name: amc rebel sst, MPG: 16.0, predicted MPG: [13.132547]\n",
      "5. Car name: ford torino, MPG: 17.0, predicted MPG: [13.046249]\n",
      "6. Car name: ford galaxie 500, MPG: 15.0, predicted MPG: [6.5326967]\n",
      "7. Car name: chevrolet impala, MPG: 14.0, predicted MPG: [4.8309555]\n",
      "8. Car name: plymouth fury iii, MPG: 14.0, predicted MPG: [5.553785]\n",
      "9. Car name: pontiac catalina, MPG: 14.0, predicted MPG: [5.0463076]\n",
      "10. Car name: amc ambassador dpl, MPG: 15.0, predicted MPG: [7.9017887]\n"
     ]
    }
   ],
   "source": [
    "# Sample predictions\n",
    "for i in range(10):\n",
    "    print(f\"{i+1}. Car name: {cars[i]}, MPG: {y[i]}, \" \n",
    "          + f\"predicted MPG: {pred[i]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "U_dpgVtfCtiS"
   },
   "source": [
    "## Simple TensorFlow Classification: Iris\n",
    "\n",
    "Classification is how a neural network attempts to classify the input into one or more classes.  The simplest way of evaluating a classification network is to track the percentage of training set items classified incorrectly.  We typically score human results in this manner.  For example, you might have taken multiple-choice exams in school in which you had to shade in a bubble for choices A, B, C, or D.  If you chose the wrong letter on a 10-question exam, you would earn a 90%.  In the same way, we can grade computers; however, most classification algorithms do not merely choose A, B, C, or D.  Computers typically report a classification as their percent confidence in each class.  Figure 3.EXAM shows how a computer and a human might respond to question number 1 on an exam.\n",
    "\n",
    "**Figure 3.EXAM: Classification Neural Network Output**\n",
    "![Classification Neural Network Output](images/class-multi-choice.png \"Classification Neural Network Output\")\n",
    "\n",
    "As you can see, the human test taker marked the first question as \"B.\" However, the computer test taker had an 80% (0.8) confidence in \"B\" and was also somewhat sure with 10% (0.1) on \"A.\" The computer then distributed the remaining points to the other two.  In the simplest sense, the machine would get 80% of the score for this question if the correct answer were \"B.\" The computer would get only 5% (0.05) of the points if the correct answer were \"D.\" \n",
    "\n",
    "We previously saw how to train a neural network to predict the MPG of a car. Based on four measurements, we will now see how to predict a class, such as the type of iris flower. The code to classify iris flowers is similar to MPG; however, there are several important differences:\n",
    "\n",
    "* The output neuron count matches the number of classes (in the case of Iris, 3).\n",
    "* The Softmax transfer function is utilized by the output layer.* The loss function is cross entropy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "aLp65T9JCtiS",
    "outputId": "63ff7475-c714-4b15-9469-a93db0f96b2c"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/100\n",
      "5/5 - 1s - loss: 2.0606 - 923ms/epoch - 185ms/step\n",
      "Epoch 2/100\n",
      "5/5 - 0s - loss: 1.4448 - 18ms/epoch - 4ms/step\n",
      "Epoch 3/100\n",
      "5/5 - 0s - loss: 1.0983 - 19ms/epoch - 4ms/step\n",
      "Epoch 4/100\n",
      "5/5 - 0s - loss: 0.9532 - 18ms/epoch - 4ms/step\n",
      "Epoch 5/100\n",
      "5/5 - 0s - loss: 0.9149 - 25ms/epoch - 5ms/step\n",
      "Epoch 6/100\n",
      "5/5 - 0s - loss: 0.8933 - 25ms/epoch - 5ms/step\n",
      "Epoch 7/100\n",
      "5/5 - 0s - loss: 0.8609 - 20ms/epoch - 4ms/step\n",
      "Epoch 8/100\n",
      "5/5 - 0s - loss: 0.8308 - 19ms/epoch - 4ms/step\n",
      "Epoch 9/100\n",
      "5/5 - 0s - loss: 0.8057 - 27ms/epoch - 5ms/step\n",
      "Epoch 10/100\n",
      "5/5 - 0s - loss: 0.7818 - 26ms/epoch - 5ms/step\n",
      "Epoch 11/100\n",
      "5/5 - 0s - loss: 0.7562 - 28ms/epoch - 6ms/step\n",
      "Epoch 12/100\n",
      "5/5 - 0s - loss: 0.7323 - 30ms/epoch - 6ms/step\n",
      "Epoch 13/100\n",
      "5/5 - 0s - loss: 0.7086 - 20ms/epoch - 4ms/step\n",
      "Epoch 14/100\n",
      "5/5 - 0s - loss: 0.6855 - 21ms/epoch - 4ms/step\n",
      "Epoch 15/100\n",
      "5/5 - 0s - loss: 0.6613 - 22ms/epoch - 4ms/step\n",
      "Epoch 16/100\n",
      "5/5 - 0s - loss: 0.6346 - 40ms/epoch - 8ms/step\n",
      "Epoch 17/100\n",
      "5/5 - 0s - loss: 0.6082 - 28ms/epoch - 6ms/step\n",
      "Epoch 18/100\n",
      "5/5 - 0s - loss: 0.5868 - 22ms/epoch - 4ms/step\n",
      "Epoch 19/100\n",
      "5/5 - 0s - loss: 0.5644 - 21ms/epoch - 4ms/step\n",
      "Epoch 20/100\n",
      "5/5 - 0s - loss: 0.5441 - 20ms/epoch - 4ms/step\n",
      "Epoch 21/100\n",
      "5/5 - 0s - loss: 0.5228 - 21ms/epoch - 4ms/step\n",
      "Epoch 22/100\n",
      "5/5 - 0s - loss: 0.5025 - 19ms/epoch - 4ms/step\n",
      "Epoch 23/100\n",
      "5/5 - 0s - loss: 0.4853 - 18ms/epoch - 4ms/step\n",
      "Epoch 24/100\n",
      "5/5 - 0s - loss: 0.4673 - 20ms/epoch - 4ms/step\n",
      "Epoch 25/100\n",
      "5/5 - 0s - loss: 0.4523 - 20ms/epoch - 4ms/step\n",
      "Epoch 26/100\n",
      "5/5 - 0s - loss: 0.4355 - 20ms/epoch - 4ms/step\n",
      "Epoch 27/100\n",
      "5/5 - 0s - loss: 0.4210 - 20ms/epoch - 4ms/step\n",
      "Epoch 28/100\n",
      "5/5 - 0s - loss: 0.4071 - 21ms/epoch - 4ms/step\n",
      "Epoch 29/100\n",
      "5/5 - 0s - loss: 0.3952 - 21ms/epoch - 4ms/step\n",
      "Epoch 30/100\n",
      "5/5 - 0s - loss: 0.3828 - 29ms/epoch - 6ms/step\n",
      "Epoch 31/100\n",
      "5/5 - 0s - loss: 0.3714 - 28ms/epoch - 6ms/step\n",
      "Epoch 32/100\n",
      "5/5 - 0s - loss: 0.3639 - 20ms/epoch - 4ms/step\n",
      "Epoch 33/100\n",
      "5/5 - 0s - loss: 0.3508 - 20ms/epoch - 4ms/step\n",
      "Epoch 34/100\n",
      "5/5 - 0s - loss: 0.3420 - 40ms/epoch - 8ms/step\n",
      "Epoch 35/100\n",
      "5/5 - 0s - loss: 0.3326 - 21ms/epoch - 4ms/step\n",
      "Epoch 36/100\n",
      "5/5 - 0s - loss: 0.3229 - 31ms/epoch - 6ms/step\n",
      "Epoch 37/100\n",
      "5/5 - 0s - loss: 0.3156 - 22ms/epoch - 4ms/step\n",
      "Epoch 38/100\n",
      "5/5 - 0s - loss: 0.3070 - 22ms/epoch - 4ms/step\n",
      "Epoch 39/100\n",
      "5/5 - 0s - loss: 0.2990 - 24ms/epoch - 5ms/step\n",
      "Epoch 40/100\n",
      "5/5 - 0s - loss: 0.2930 - 31ms/epoch - 6ms/step\n",
      "Epoch 41/100\n",
      "5/5 - 0s - loss: 0.2841 - 25ms/epoch - 5ms/step\n",
      "Epoch 42/100\n",
      "5/5 - 0s - loss: 0.2761 - 23ms/epoch - 5ms/step\n",
      "Epoch 43/100\n",
      "5/5 - 0s - loss: 0.2720 - 24ms/epoch - 5ms/step\n",
      "Epoch 44/100\n",
      "5/5 - 0s - loss: 0.2632 - 23ms/epoch - 5ms/step\n",
      "Epoch 45/100\n",
      "5/5 - 0s - loss: 0.2569 - 26ms/epoch - 5ms/step\n",
      "Epoch 46/100\n",
      "5/5 - 0s - loss: 0.2519 - 23ms/epoch - 5ms/step\n",
      "Epoch 47/100\n",
      "5/5 - 0s - loss: 0.2445 - 24ms/epoch - 5ms/step\n",
      "Epoch 48/100\n",
      "5/5 - 0s - loss: 0.2395 - 24ms/epoch - 5ms/step\n",
      "Epoch 49/100\n",
      "5/5 - 0s - loss: 0.2329 - 23ms/epoch - 5ms/step\n",
      "Epoch 50/100\n",
      "5/5 - 0s - loss: 0.2271 - 23ms/epoch - 5ms/step\n",
      "Epoch 51/100\n",
      "5/5 - 0s - loss: 0.2220 - 22ms/epoch - 4ms/step\n",
      "Epoch 52/100\n",
      "5/5 - 0s - loss: 0.2175 - 23ms/epoch - 5ms/step\n",
      "Epoch 53/100\n",
      "5/5 - 0s - loss: 0.2115 - 22ms/epoch - 4ms/step\n",
      "Epoch 54/100\n",
      "5/5 - 0s - loss: 0.2094 - 22ms/epoch - 4ms/step\n",
      "Epoch 55/100\n",
      "5/5 - 0s - loss: 0.2045 - 33ms/epoch - 7ms/step\n",
      "Epoch 56/100\n",
      "5/5 - 0s - loss: 0.1996 - 34ms/epoch - 7ms/step\n",
      "Epoch 57/100\n",
      "5/5 - 0s - loss: 0.1943 - 23ms/epoch - 5ms/step\n",
      "Epoch 58/100\n",
      "5/5 - 0s - loss: 0.1898 - 51ms/epoch - 10ms/step\n",
      "Epoch 59/100\n",
      "5/5 - 0s - loss: 0.1855 - 27ms/epoch - 5ms/step\n",
      "Epoch 60/100\n",
      "5/5 - 0s - loss: 0.1823 - 28ms/epoch - 6ms/step\n",
      "Epoch 61/100\n",
      "5/5 - 0s - loss: 0.1799 - 22ms/epoch - 4ms/step\n",
      "Epoch 62/100\n",
      "5/5 - 0s - loss: 0.1746 - 30ms/epoch - 6ms/step\n",
      "Epoch 63/100\n",
      "5/5 - 0s - loss: 0.1715 - 23ms/epoch - 5ms/step\n",
      "Epoch 64/100\n",
      "5/5 - 0s - loss: 0.1674 - 39ms/epoch - 8ms/step\n",
      "Epoch 65/100\n",
      "5/5 - 0s - loss: 0.1639 - 21ms/epoch - 4ms/step\n",
      "Epoch 66/100\n",
      "5/5 - 0s - loss: 0.1611 - 28ms/epoch - 6ms/step\n",
      "Epoch 67/100\n",
      "5/5 - 0s - loss: 0.1587 - 23ms/epoch - 5ms/step\n",
      "Epoch 68/100\n",
      "5/5 - 0s - loss: 0.1554 - 17ms/epoch - 3ms/step\n",
      "Epoch 69/100\n",
      "5/5 - 0s - loss: 0.1517 - 19ms/epoch - 4ms/step\n",
      "Epoch 70/100\n",
      "5/5 - 0s - loss: 0.1503 - 21ms/epoch - 4ms/step\n",
      "Epoch 71/100\n",
      "5/5 - 0s - loss: 0.1477 - 33ms/epoch - 7ms/step\n",
      "Epoch 72/100\n",
      "5/5 - 0s - loss: 0.1443 - 25ms/epoch - 5ms/step\n",
      "Epoch 73/100\n",
      "5/5 - 0s - loss: 0.1418 - 26ms/epoch - 5ms/step\n",
      "Epoch 74/100\n",
      "5/5 - 0s - loss: 0.1399 - 36ms/epoch - 7ms/step\n",
      "Epoch 75/100\n",
      "5/5 - 0s - loss: 0.1384 - 20ms/epoch - 4ms/step\n",
      "Epoch 76/100\n",
      "5/5 - 0s - loss: 0.1351 - 21ms/epoch - 4ms/step\n",
      "Epoch 77/100\n",
      "5/5 - 0s - loss: 0.1355 - 18ms/epoch - 4ms/step\n",
      "Epoch 78/100\n",
      "5/5 - 0s - loss: 0.1321 - 19ms/epoch - 4ms/step\n",
      "Epoch 79/100\n",
      "5/5 - 0s - loss: 0.1312 - 17ms/epoch - 3ms/step\n",
      "Epoch 80/100\n",
      "5/5 - 0s - loss: 0.1283 - 19ms/epoch - 4ms/step\n",
      "Epoch 81/100\n",
      "5/5 - 0s - loss: 0.1272 - 19ms/epoch - 4ms/step\n",
      "Epoch 82/100\n",
      "5/5 - 0s - loss: 0.1254 - 18ms/epoch - 4ms/step\n",
      "Epoch 83/100\n",
      "5/5 - 0s - loss: 0.1212 - 23ms/epoch - 5ms/step\n",
      "Epoch 84/100\n",
      "5/5 - 0s - loss: 0.1204 - 18ms/epoch - 4ms/step\n",
      "Epoch 85/100\n",
      "5/5 - 0s - loss: 0.1192 - 19ms/epoch - 4ms/step\n",
      "Epoch 86/100\n",
      "5/5 - 0s - loss: 0.1170 - 18ms/epoch - 4ms/step\n",
      "Epoch 87/100\n",
      "5/5 - 0s - loss: 0.1150 - 19ms/epoch - 4ms/step\n",
      "Epoch 88/100\n",
      "5/5 - 0s - loss: 0.1145 - 21ms/epoch - 4ms/step\n",
      "Epoch 89/100\n",
      "5/5 - 0s - loss: 0.1129 - 20ms/epoch - 4ms/step\n",
      "Epoch 90/100\n",
      "5/5 - 0s - loss: 0.1119 - 19ms/epoch - 4ms/step\n",
      "Epoch 91/100\n",
      "5/5 - 0s - loss: 0.1089 - 44ms/epoch - 9ms/step\n",
      "Epoch 92/100\n",
      "5/5 - 0s - loss: 0.1106 - 50ms/epoch - 10ms/step\n",
      "Epoch 93/100\n",
      "5/5 - 0s - loss: 0.1068 - 34ms/epoch - 7ms/step\n",
      "Epoch 94/100\n",
      "5/5 - 0s - loss: 0.1085 - 34ms/epoch - 7ms/step\n",
      "Epoch 95/100\n",
      "5/5 - 0s - loss: 0.1053 - 28ms/epoch - 6ms/step\n",
      "Epoch 96/100\n",
      "5/5 - 0s - loss: 0.1072 - 31ms/epoch - 6ms/step\n",
      "Epoch 97/100\n",
      "5/5 - 0s - loss: 0.1005 - 34ms/epoch - 7ms/step\n",
      "Epoch 98/100\n",
      "5/5 - 0s - loss: 0.1047 - 36ms/epoch - 7ms/step\n",
      "Epoch 99/100\n",
      "5/5 - 0s - loss: 0.0984 - 42ms/epoch - 8ms/step\n",
      "Epoch 100/100\n",
      "5/5 - 0s - loss: 0.1024 - 31ms/epoch - 6ms/step\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.History at 0x7f7a74758d90>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import io\n",
    "import requests\n",
    "import numpy as np\n",
    "from sklearn import metrics\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense, Activation\n",
    "from tensorflow.keras.callbacks import EarlyStopping\n",
    "\n",
    "df = pd.read_csv(\n",
    "    \"https://data.heatonresearch.com/data/t81-558/iris.csv\", \n",
    "    na_values=['NA', '?'])\n",
    "\n",
    "# Convert to numpy - Classification\n",
    "x = df[['sepal_l', 'sepal_w', 'petal_l', 'petal_w']].values\n",
    "dummies = pd.get_dummies(df['species']) # Classification\n",
    "species = dummies.columns\n",
    "y = dummies.values\n",
    "\n",
    "\n",
    "# Build neural network\n",
    "model = Sequential()\n",
    "model.add(Dense(50, input_dim=x.shape[1], activation='relu')) # Hidden 1\n",
    "model.add(Dense(25, activation='relu')) # Hidden 2\n",
    "model.add(Dense(y.shape[1],activation='softmax')) # Output\n",
    "\n",
    "model.compile(loss='categorical_crossentropy', optimizer='adam')\n",
    "model.fit(x,y,verbose=2,epochs=100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "QPM30WdBCtiS",
    "outputId": "455a6d0f-41f9-4e43-c538-6311a5c81299"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Index(['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'], dtype='object')\n"
     ]
    }
   ],
   "source": [
    "# Print out number of species found:\n",
    "\n",
    "print(species)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "dM8-xyDxCtiS"
   },
   "source": [
    "Now that you have a neural network trained, we would like to be able to use it. The following code makes use of our neural network. Exactly like before, we will generate predictions. Notice that three values come back for each of the 150 iris flowers. There were three types of iris (Iris-setosa, Iris-versicolor, and Iris-virginica).  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "3YzlVpw-CtiS",
    "outputId": "7b664d3d-7092-44f9-b124-c3404da038c4"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shape: (150, 3)\n",
      "[[9.9478287e-01 5.2075940e-03 9.5348660e-06]\n",
      " [9.8996514e-01 1.0009427e-02 2.5472993e-05]\n",
      " [9.9217004e-01 7.8077433e-03 2.2259781e-05]\n",
      " [9.8900187e-01 1.0962254e-02 3.5841138e-05]\n",
      " [9.9483585e-01 5.1541878e-03 1.0017948e-05]\n",
      " [9.9543911e-01 4.5537245e-03 7.2729345e-06]\n",
      " [9.9191731e-01 8.0558369e-03 2.6869655e-05]\n",
      " [9.9353105e-01 6.4554708e-03 1.3498360e-05]\n",
      " [9.8614627e-01 1.3796916e-02 5.6765439e-05]\n",
      " [9.9109799e-01 8.8818911e-03 2.0043452e-05]]\n"
     ]
    }
   ],
   "source": [
    "pred = model.predict(x)\n",
    "print(f\"Shape: {pred.shape}\")\n",
    "print(pred[0:10])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "JCay-JrvCtiS"
   },
   "source": [
    "If you would like to turn of scientific notation, the following line can be used:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "nXZne7ZICtiS"
   },
   "outputs": [],
   "source": [
    "np.set_printoptions(suppress=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "nOvMqI7QCtiS"
   },
   "source": [
    "Now we see these values rounded up."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "F9PSDexjCtiS",
    "outputId": "d06e6901-8168-4835-a998-ee1d43bb65d2"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]\n",
      " [1 0 0]]\n"
     ]
    }
   ],
   "source": [
    "print(y[0:10])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "qDC7hxqECtiS"
   },
   "source": [
    "Usually, the program considers the column with the highest prediction to be the prediction of the neural network.  It is easy to convert the predictions to the expected iris species.  The argmax function finds the index of the maximum prediction for each row."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "367mbx_PCtiT",
    "outputId": "bf69a471-4080-4628-ebc5-9571d408881d"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Predictions: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 2 1\n",
      " 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2]\n",
      "Expected: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
      " 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1\n",
      " 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2\n",
      " 2 2]\n"
     ]
    }
   ],
   "source": [
    "predict_classes = np.argmax(pred,axis=1)\n",
    "expected_classes = np.argmax(y,axis=1)\n",
    "print(f\"Predictions: {predict_classes}\")\n",
    "print(f\"Expected: {expected_classes}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "lrcy0Q4xCtiT"
   },
   "source": [
    "Of course, it is straightforward to turn these indexes back into iris species. We use the species list that we created earlier."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "NTORTvygCtiT",
    "outputId": "a931a4d1-3204-42de-af37-a366ec2ba353"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Index(['Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n",
      "       'Iris-setosa', 'Iris-setosa', 'Iris-setosa', 'Iris-setosa',\n",
      "       'Iris-setosa'],\n",
      "      dtype='object')\n"
     ]
    }
   ],
   "source": [
    "print(species[predict_classes[1:10]])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "Ljez1ZRACtiT"
   },
   "source": [
    "Accuracy might be a more easily understood error metric.  It is essentially a test score.  For all of the iris predictions, what percent were correct?  The downside is it does not consider how confident the neural network was in each prediction."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "zth2S2OcCtiT",
    "outputId": "f68a373c-f84e-4d01-8e83-dc22199e76ff"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 0.98\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "correct = accuracy_score(expected_classes,predict_classes)\n",
    "print(f\"Accuracy: {correct}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "jY07aiLICtiT"
   },
   "source": [
    "The code below performs two ad hoc predictions.  The first prediction is a single iris flower, and the second predicts two iris flowers.  Notice that the **argmax** in the second prediction requires **axis=1**?  Since we have a 2D array now, we must specify which axis to take the **argmax** over.  The value **axis=1** specifies we want the max column index for each row."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "FZUSWVGnCtiT",
    "outputId": "d98e7cc3-7e10-44f0-a5cb-b858f3c4c850"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.00343206 0.17186154 0.8247064 ]]\n",
      "Predict that [[5. 3. 4. 2.]] is: Iris-virginica\n"
     ]
    }
   ],
   "source": [
    "sample_flower = np.array( [[5.0,3.0,4.0,2.0]], dtype=float)\n",
    "pred = model.predict(sample_flower)\n",
    "print(pred)\n",
    "pred = np.argmax(pred)\n",
    "print(f\"Predict that {sample_flower} is: {species[pred]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ENSZaaRICtiT"
   },
   "source": [
    "You can also predict two sample flowers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "fdSSkkmwCtiT",
    "outputId": "68d48b43-ea6b-4c5c-a226-9c19c0ae5060"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.00343206 0.17186162 0.8247064 ]\n",
      " [0.9854916  0.01445759 0.00005079]]\n",
      "Predict that these two flowers [[5.  3.  4.  2. ]\n",
      " [5.2 3.5 1.5 0.8]] \n",
      "are: Index(['Iris-virginica', 'Iris-setosa'], dtype='object')\n"
     ]
    }
   ],
   "source": [
    "sample_flower = np.array( [[5.0,3.0,4.0,2.0],[5.2,3.5,1.5,0.8]],\\\n",
    "        dtype=float)\n",
    "pred = model.predict(sample_flower)\n",
    "print(pred)\n",
    "pred = np.argmax(pred,axis=1)\n",
    "print(f\"Predict that these two flowers {sample_flower} \")\n",
    "print(f\"are: {species[pred]}\")"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "colab": {
   "collapsed_sections": [],
   "name": "Copy of Copy of t81_558_class_03_2_keras.ipynb",
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3.9 (tensorflow)",
   "language": "python",
   "name": "tensorflow"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
